import {
  ObjectOnlyPushSet,
  removeObjectOnlyPushSet,
} from '../../../../../global/Func/ObjectOnlyPushSet_operate';
import { addEvent } from '../Func/addEvent';
import { removeEvent } from '../Func/removeEvent';
import type {
  typ_event_keys,
  typ_seek_event_arr,
  typ_seek_func_arr,
  typ_seek_targetEl_arr,
} from '../Types';
import type { listenEvent_info } from './cla_listenEvent_info';
import {
  listenEvent_info_mana,
  locate_uniArr_info,
} from './cla_listenEvent_info_mana';

const listenEvent_manaTag = 'listenEvent_mana';

export class listenEvent_mana {
  get [Symbol.toStringTag]() {
    return listenEvent_manaTag;
  }

  constructor(spacename: string) {
    this.spacename = spacename;
  }

  /**
   * 当前 域名
   */
  spacename: string;

  freeze_data: listenEvent_info[] = [];

  /**
   * 正在 绑定 的 事件 信息集
   */
  on = new listenEvent_info_mana();

  /**
   * 已 解除 的 事件 信息集
   */
  off = new listenEvent_info_mana();

  /**
   * 添加事件 信息 添加 到 on 集合里
   */
  addEventListen(
    targetEl: HTMLElement,
    event: typ_event_keys,
    fn: Function,
    options?: boolean
  ) {
    addEvent(targetEl, event, fn, options);
    this.on.addInfo(targetEl, event, fn);
  }

  /**
   * 移出 on 事件 信息 添加 到 off 集合里
   */
  removeEventListen(
    targetEl: HTMLElement,
    event: typ_event_keys,
    fn: Function,
    options?: boolean
  ) {
    removeEvent(targetEl, event, fn, options);
    let deleteArr = this.on.removeInfo(targetEl, event, fn);
    for (const uniInfo of deleteArr) {
      let { targetEl, event, fn } = uniInfo;
      this.off.addInfo(targetEl, event, fn);
    }
  }

  /**
   * 根据 给定 的数据信息 判定 绑定 的 信息组 进行 解绑
   */
  freeze(
    targetElArr: typ_seek_targetEl_arr,
    eventArr?: typ_seek_event_arr,
    fnArr?: typ_seek_func_arr
  ) {
    let ret = this.on.stack;

    ret = locate_uniArr_info(ret, { targetElArr, eventArr, fnArr });

    for (const uniInfo of ret) {
      let { targetEl, event, fn, options } = uniInfo;
      this.removeEventListen(targetEl, event, fn, options);
      ObjectOnlyPushSet(this.freeze_data, uniInfo);
      uniInfo.frozen_status = true;
    }

    return ret;
  }

  /**
   * 禁用 当前 所有 绑定 事件
   * @returns
   */
  freeze_all() {
    let ret = [...this.on.stack];

    for (const uniInfo of ret) {
      let { targetEl, event, fn, options } = uniInfo;
      this.removeEventListen(targetEl, event, fn, options);
      ObjectOnlyPushSet(this.freeze_data, uniInfo);
      uniInfo.frozen_status = true;
    }

    return ret;
  }

  /**
   * 根据 给定 的数据信息 判定 绑定 的 信息组 进行 绑定
   */
  unfreeze(
    targetElArr: typ_seek_targetEl_arr,
    eventArr?: typ_seek_event_arr,
    fnArr?: typ_seek_func_arr
  ) {
    let ret = this.freeze_data;

    ret = locate_uniArr_info(ret, { targetElArr, eventArr, fnArr });

    for (const uniInfo of ret) {
      let { targetEl, event, fn, options } = uniInfo;
      this.addEventListen(targetEl, event, fn, options);
      removeObjectOnlyPushSet(this.freeze_data, uniInfo);
      uniInfo.frozen_status = false;
    }

    return ret;
  }

  /**
   * 解除 所有 当前 名下 的 freeze 信息
   */
  unfreezeAll() {
    for (const uniInfo of this.freeze_data) {
      let { targetEl, event, fn, options } = uniInfo;

      this.addEventListen(targetEl, event, fn, options);

      uniInfo.frozen_status = false;
    }
    this.freeze_data = [];
  }
}
